#include "device.h"
#include "component.h"

/* 调试打印接口 */
#define BATTERY_LOG(format, ...)    OSAL_LOG(format, ##__VA_ARGS__)

/* 电池电量采集的ADC通道 */
#define BATTERY_ADC_CHANNEL				vADC_0

/* 应急电源电压采集的ADC通道 */
#define USB_EMERGENCY_ADC_CHANNEL		vADC_3

/* 电池电量采集的ADC通道检测使能管脚 */
#define BATTERY_ADC_CHECK_ENABLE()      Device_Write(vPIN_C3, NULL, 0, 1)   //打开电量采集ADC检测
#define BATTERY_ADC_CHECK_DISABLE()     Device_Write(vPIN_C3, NULL, 0, 0)   //关闭电量采集ADC检测

/* 电量100%/10%/0%时的电压值 */
#ifdef  BATTERY_6_0V
    #define BATTERY_VF_VAL 				400  // 0.4v	二极管电压 VF 二极管正向导通压降
	#define BATTERY_ADC_VAL_100			6000 //6.00v	100%  满电
	#define BATTERY_ADC_VAL_20			4800 //4.8v	    20%   低电量
	#define BATTERY_ADC_VAL_10			4600 //4.6v		10%   低电量
	#define BATTERY_ADC_VAL_0			4200 //4.15v	0%    0电量（关机不响应任何动作）
#elif defined(BATTERY_4_5V)  
	#define BATTERY_ADC_VAL_100			4500 //4.5v	    100%  满电
	#define BATTERY_ADC_VAL_20			3750 //3.75v	20%   低电量
	#define BATTERY_ADC_VAL_10			3650 //3.65v	10%   低电量
	#define BATTERY_ADC_VAL_0			3550 //4.15v	0%    0电量（关机不响应任何动作）
#else 
	#define BATTERY_ADC_VAL_100			8000 //8.00v	100%  满电
	#define BATTERY_ADC_VAL_20			6800 //6.8v		20%   低电量
	#define BATTERY_ADC_VAL_10			6600 //6.6v		10%   低电量
	#define BATTERY_ADC_VAL_0			6000 //6.0v		0%    0电量（关机不响应任何动作）
#endif

#define     BATTERY_LEVEL_100           100
#define     BATTERY_LEVEL_20            20
#define     BATTERY_LEVEL_10            10
#define     BATTERY_LEVEL_0             0

#define LOCK_BATTERY_CHANGE_THRESHOLD   30  //电量增大变化阈值

/* USB应急电源检测电压阈值 */
#define USB_EMERGENCY_VOLTAGE			BATTERY_ADC_VAL_0

typedef enum
{
    BATTERY_UPDATE_MODE_ATE = 1,
    BATTERY_UPDATE_MODE_NORMAL = 2,
}Battery_UpdateMode_enum_t;

/* 电池电量值（0~100%） */
__EFRAM static int batterylevel = -1;
__EFRAM static FlagStatus batteryInitFlag = RESET;
int gBatteryAdcvoltage = 0;


//读取电源电压
static int Battery_GetVoltage(void)
{
    int voltage  =  Device_Read(BATTERY_ADC_CHANNEL, NULL, 0, 0);
/* 硬件有增加二极管，需要添加电压补偿 */
#if BATTERY_VF_VAL
    voltage += BATTERY_VF_VAL;
#endif
    gBatteryAdcvoltage = voltage;
    return voltage; //换算成电池的电压
}

//读取USB应急电源电压
static int USB_Emergency_GetVoltage(void)
{
    int voltage  = (int)Device_Read(USB_EMERGENCY_ADC_CHANNEL, NULL, 0, 0); 
	return voltage; //换算成电池的电压
}

/**
 * @brief  更新电量ADC值
 *
 * @note   电量有小的回升时，直接滤除掉
 */
static void Battery_Voltage2Percent(int batvolts, uint8_t getMode)
{
    static int lastBatvolts;
    int level = 0;

    if (batvolts != lastBatvolts)
    {
        lastBatvolts = batvolts;

        if (batvolts >= BATTERY_ADC_VAL_100)
        {
            level = BATTERY_LEVEL_100;
        }
        else if (batvolts <= BATTERY_ADC_VAL_0)
        {
            level = BATTERY_LEVEL_0;
        }
        else if (batvolts > BATTERY_ADC_VAL_20)
        {
            level = (batvolts - BATTERY_ADC_VAL_20) * (BATTERY_LEVEL_100 - BATTERY_LEVEL_20) /
                        (BATTERY_ADC_VAL_100 - BATTERY_ADC_VAL_20) + BATTERY_LEVEL_20;
        }
        else if (batvolts > BATTERY_ADC_VAL_10)
        {
            level = (batvolts - BATTERY_ADC_VAL_10) * (BATTERY_LEVEL_20 - BATTERY_LEVEL_10) /
                        (BATTERY_ADC_VAL_20 - BATTERY_ADC_VAL_10) + BATTERY_LEVEL_10;
        }
        else
        {
            level = (batvolts - BATTERY_ADC_VAL_0) * (BATTERY_LEVEL_10 - BATTERY_LEVEL_0) /
                    (BATTERY_ADC_VAL_10 - BATTERY_ADC_VAL_0);
        }

        if(getMode == BATTERY_UPDATE_MODE_ATE)
        {
            BATTERY_LOG("ATE bat update: %d",level);
            batterylevel = level;
        }
        else if(getMode == BATTERY_UPDATE_MODE_NORMAL)
        {
            /* 第一次上电或者电量降低了或者电量增大了30%以上，就刷新电量值 */
            if ((level >= (batterylevel + LOCK_BATTERY_CHANGE_THRESHOLD)) || (level < batterylevel) ||
                (batterylevel < 0) || level == BATTERY_ADC_VAL_100)
            {
                BATTERY_LOG("bat update: %d",level);
                batterylevel = level;
            }
        }

		BATTERY_LOG("vol=%d level=%d bat=%d",batvolts, level,batterylevel);
    }
}
//获取当前电池电量百分比，只有产测用，实时更新
uint8_t Battery_Ate_Get(void)
{
    int vol = Battery_GetVoltage();
    Battery_Voltage2Percent(vol, BATTERY_UPDATE_MODE_ATE);

    if (batterylevel < 0)
        return 0;
    return (uint8_t)batterylevel;
}
//获取当前电池电量百分比（网络任务会获取电量),每次上电或者唤醒才会更新
uint8_t Battery_Get(void)
{
    if (batterylevel < 0)
        return 0;
    return (uint8_t)batterylevel;
}


//获取当前电池电压，每次上电或者唤醒才会更新
uint16_t Battery_VoltageGet(void)
{
    if (gBatteryAdcvoltage < 0)
    {
        return 0;
    }

    return (uint16_t)gBatteryAdcvoltage;
}

//处理唤醒事件
static void Battery_ProcessWake(uint8_t report)
{
    if (batteryInitFlag == RESET)
    {
        int vol = Battery_GetVoltage();
        Battery_Voltage2Percent(vol, BATTERY_UPDATE_MODE_NORMAL);
		batteryInitFlag = SET;
	}
	else
    {
        if (report)
        {
            OSAL_MessagePublish(&batterylevel, sizeof(batterylevel));//消息上报,通知应用层
        }
    }
}

/**
 * @brief 电压持续性判断
 * 
 * @note 
 * 
 */
void OSAL_StartHook(void)
{
    BATTERY_ADC_CHECK_ENABLE();
    Device_DelayUs(200);
    Battery_ProcessWake(0);

    if(batterylevel)
	{
	}
	else
	{
		while(1)
		{
            batteryInitFlag = RESET;
			Battery_ProcessWake(0);
			int usbVoltage = USB_Emergency_GetVoltage();
			if(usbVoltage >= USB_EMERGENCY_VOLTAGE)
			{
				BATTERY_LOG("USB Emergency vol: %d",usbVoltage);
				break;
			}
			
			if(batterylevel)
			{
				BATTERY_LOG("Battery legal");
				break;
			}
			
			Device_FeedDog();
			Device_DelayMs(20);
		}
	}
}

/**
  * @brief  Battery任务函数
  *
  * @note   1.任务函数内不能写阻塞代码
  *         2.任务函数每次运行只处理一个事件
  *         
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Battery_Task(uint32_t event)
{
	/* 系统启动事件 */
	if (event & EVENT_SYS_START)
	{
		BATTERY_LOG("Battery task start");
        #ifndef SLAVE_DEVICE
        /* 注册对外开放的API接口 */
        SYS_API(Battery_Get);
        SYS_API(Battery_Ate_Get);
        SYS_API(Battery_VoltageGet);
        #endif
		Battery_ProcessWake(1);
		return ( event ^ EVENT_SYS_START );
	}
	
	/* 系统休眠事件 */
	if (event & EVENT_SYS_SLEEP)
	{
        BATTERY_LOG("Battery task sleep");
        BATTERY_ADC_CHECK_DISABLE();
        Device_Disable(BATTERY_ADC_CHANNEL);
        batteryInitFlag = RESET;
		return ( event ^ EVENT_SYS_SLEEP );
    }
	
	return 0;
}
COMPONENT_TASK_EXPORT(COMP_BATTERY, Battery_Task, 0);
